cmake_minimum_required(VERSION 3.10)
# set the project name
project(led C ASM)

# 添加STM32标准库全局宏STM32F429_439xx&&USE_STDPERIPH_DRIVER
add_definitions(-DSTM32F429_439xx
                -DUSE_STDPERIPH_DRIVER
)

# set the project version
set(PROJECT_VERSION_MAJOR 1)
set(PROJECT_VERSION_MINOR 0)
set(PROJECT_VERSION_PATCH 0)

# 指定编译工具
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
set(CMAKE_ASM_COMPILER arm-none-eabi-gcc)
#set(CMAKE_C_COMPILER arm-none-eabi-g++)
set(CMAKE_OBJDUMP arm-none-eabi-objdump)
set(CMAKE_OBJCOPY arm-none-eabi-objcopy) 
set(CMAKE_SIZE arm-none-eabi-size)

set(CMAKE_C_FLAGS_DEBUG "-O0 -g")
set(CMAKE_C_FLAGS_RELEASE "-O3")

# 设置芯片参数
set(CPU "-mcpu=cortex-m4") 
set(FPU "-mfpu=fpv4-sp-d16")
set(FLOAT_ABI "-mfloat-abi=hard")

set(MCU_FLAGS "${CPU} -mthumb ${FPU} ${FLOAT_ABI}")
# 指定C编译器编译选项
set(CMAKE_C_FLAGS "${MCU_FLAGS} -std=gnu11 -Wall -fdata-sections -ffunction-sections")
# 指定C++编译器编译选项
set(CMAKE_CXX_FLAGS "${MCU_FLAGS} -std=g++11 -fno-rtti -fno-exceptions -fno-builtin -Wall -fdata-sections -ffunction-sections")
# 指定汇编器编译选项
set(CMAKE_ASM_FLAGS "${MCU_FLAGS} -x assembler-with-cpp")
# 指定连接器链接选项
set(LINKER_SCRIPT ${PROJECT_SOURCE_DIR}/tools/STM32F439NI_FLASH.ld)
set(CMAKE_EXE_LINKER_FLAGS "-T${LINKER_SCRIPT} --specs=nosys.specs -Wl,-Map=${PROJECT_BINARY_DIR}/${PROJECT_NAME}.map -Wl,--gc-sections -static --specs=nano.specs ${MCU_FLAGS} -Wl,--start-group -lc -lm -Wl,--end-group")

# 指定生成目标文件和库文件的目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/share)

# 指定config文件，可以根据自己需要设置此项
set(CONFIG_INPUT_DIR ${PROJECT_SOURCE_DIR}/config)
set(CONFIG_OUTPUT_DIR ${PROJECT_SOURCE_DIR}/include)
configure_file(${CONFIG_INPUT_DIR}/config.h.in ${CONFIG_OUTPUT_DIR}/config.h)

# 指定整个项目头文件目录
include_directories(${PROJECT_SOURCE_DIR}/include
                    ${PROJECT_SOURCE_DIR}/stm32f4_stdlib
                    ${PROJECT_SOURCE_DIR}/stm32f4_stdlib/core
                    ${PROJECT_SOURCE_DIR}/stm32f4_stdlib/device/inc
                    ${PROJECT_SOURCE_DIR}/stm32f4_stdlib/system/inc
)

# 指定了汇编编译器可以不开启这一项，这项意在指示汇编代码
#set_property(SOURCE stm32f4_stdlib/startup/startup_stm32f429_439xx.s PROPERTY LANGUAGE C) 

add_library(stm32f4_stdlib
    stm32f4_stdlib/startup/startup_stm32f429_439xx.s
    stm32f4_stdlib/system/src/system_stm32f4xx.c
    stm32f4_stdlib/device/src/misc.c
    stm32f4_stdlib/device/src/stm32f4xx_adc.c
    stm32f4_stdlib/device/src/stm32f4xx_can.c
    stm32f4_stdlib/device/src/stm32f4xx_cec.c
    stm32f4_stdlib/device/src/stm32f4xx_crc.c
    stm32f4_stdlib/device/src/stm32f4xx_cryp_aes.c
    stm32f4_stdlib/device/src/stm32f4xx_cryp.c
    stm32f4_stdlib/device/src/stm32f4xx_cryp_des.c
    stm32f4_stdlib/device/src/stm32f4xx_cryp_tdes.c
    stm32f4_stdlib/device/src/stm32f4xx_dac.c
    stm32f4_stdlib/device/src/stm32f4xx_dbgmcu.c
    stm32f4_stdlib/device/src/stm32f4xx_dcmi.c
    stm32f4_stdlib/device/src/stm32f4xx_dfsdm.c
    stm32f4_stdlib/device/src/stm32f4xx_dma2d.c
    stm32f4_stdlib/device/src/stm32f4xx_dma.c
    stm32f4_stdlib/device/src/stm32f4xx_dsi.c
    stm32f4_stdlib/device/src/stm32f4xx_exti.c
    stm32f4_stdlib/device/src/stm32f4xx_flash.c
    stm32f4_stdlib/device/src/stm32f4xx_flash_ramfunc.c
    stm32f4_stdlib/device/src/stm32f4xx_fmc.c
    stm32f4_stdlib/device/src/stm32f4xx_fmpi2c.c
#    stm32f4_stdlib/device/src/stm32f4xx_fsmc.c
    stm32f4_stdlib/device/src/stm32f4xx_gpio.c
    stm32f4_stdlib/device/src/stm32f4xx_hash.c
    stm32f4_stdlib/device/src/stm32f4xx_hash_md5.c
    stm32f4_stdlib/device/src/stm32f4xx_hash_sha1.c
    stm32f4_stdlib/device/src/stm32f4xx_i2c.c
    stm32f4_stdlib/device/src/stm32f4xx_iwdg.c
    stm32f4_stdlib/device/src/stm32f4xx_lptim.c
    stm32f4_stdlib/device/src/stm32f4xx_ltdc.c
    stm32f4_stdlib/device/src/stm32f4xx_pwr.c
    stm32f4_stdlib/device/src/stm32f4xx_qspi.c
    stm32f4_stdlib/device/src/stm32f4xx_rcc.c
    stm32f4_stdlib/device/src/stm32f4xx_rng.c
    stm32f4_stdlib/device/src/stm32f4xx_rtc.c
    stm32f4_stdlib/device/src/stm32f4xx_sai.c
    stm32f4_stdlib/device/src/stm32f4xx_sdio.c
    stm32f4_stdlib/device/src/stm32f4xx_spdifrx.c
    stm32f4_stdlib/device/src/stm32f4xx_spi.c
    stm32f4_stdlib/device/src/stm32f4xx_syscfg.c
    stm32f4_stdlib/device/src/stm32f4xx_tim.c
    stm32f4_stdlib/device/src/stm32f4xx_usart.c
    stm32f4_stdlib/device/src/stm32f4xx_wwdg.c
)

# 这里需要自己添加源文件，指定目录和文件名
set(user_SRCS
    src/main.c
    src/stm32f4xx_it.c
    src/led.c
    src/key.c
    src/exti_key.c
    src/nvic_conf.c
    src/systick_delay.c
    src/system_uart.c
)

# 生成可执行文件，开发者代码
add_executable(${PROJECT_NAME}.elf ${user_SRCS}) 

# 链接库文件，生成目标文件
target_link_libraries(${PROJECT_NAME}.elf PUBLIC
    stm32f4_stdlib
)

# 指定目标头文件目录
target_include_directories(${PROJECT_NAME}.elf PUBLIC
                           ${PROJECT_SOURCE_DIR}/include
                           ${PROJECT_SOURCE_DIR}/stm32f4_stdlib
                           ${PROJECT_SOURCE_DIR}/stm32f4_stdlib/core
                           ${PROJECT_SOURCE_DIR}/stm32f4_stdlib/device/inc
                           ${PROJECT_SOURCE_DIR}/stm32f4_stdlib/system/inc
)

# 指定输出二进制文件目录 ../build/led.elf
set(ELF_FILE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.elf")
set(BIN_FILE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.bin")
set(HEX_FILE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.hex")
set(ASM_FILE "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.S")

# 使用生成的elf文件重新生成hex和bin文件，用于烧写
add_custom_command(TARGET "${PROJECT_NAME}.elf" POST_BUILD
    COMMENT "Building ${BIN_FILE} ..."
    COMMAND ${CMAKE_OBJDUMP} -S ${ELF_FILE} > ${ASM_FILE}
    COMMAND ${CMAKE_OBJCOPY} -O binary ${ELF_FILE} ${BIN_FILE}
    COMMAND ${CMAKE_OBJCOPY} -O ihex   ${ELF_FILE} ${HEX_FILE}
    COMMAND ${CMAKE_SIZE} ${ELF_FILE} ${HEX_FILE}
    COMMENT "Image component sizes"
)

message("==================================================================")
message(STATUS "Build compiler: " ${CMAKE_C_COMPILER})
message(STATUS "Project name: " ${PROJECT_NAME})
message(STATUS "Project version: " ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}) 
message(STATUS "Source directory: " ${PROJECT_SOURCE_DIR})
message(STATUS "Binary directory: " ${PROJECT_BINARY_DIR})
message("==================================================================")

